#include "System/FLASH/flash.h"

/**
 * @brief  初始化 Flash 模块（检查是否可写）
 */
void flash_init(void)
{
    FLASH_INIT_FUN();
}

/**
 * @brief  擦除指定页
 * @param  addr: 页起始地址
 * @retval 0: 成功，1: 失败
 */
uint8_t flash_erase_page(uint32_t addr)
{
    if (addr < FLASH_BASE_ADDR || addr >= FLASH_END_ADDR)
        return 1;

    FLASH_UNLOCK();
    uint8_t ret = FLASH_ERASE_PAGE(addr);
    FLASH_LOCK();
    return ret;
}

/**
 * @brief  写入数据到 Flash（带擦除）
 * @param  addr: 起始地址（必须是页对齐）
 * @param  buf: 数据缓冲区
 * @param  size: 数据大小（字节）
 * @retval 0: 成功，1: 地址错误，2: 擦除失败，3: 写入失败
 */
uint8_t flash_write(uint32_t addr, const uint32_t *buf, uint32_t size)
{
    if (addr < FLASH_BASE_ADDR || addr + size >= FLASH_END_ADDR || addr % 4 != 0 || size % 4 != 0)
        return 1;

#if FLASH_AUTO_ERASE_BEFORE_WRITE
    uint32_t page_addr = addr & ~(FLASH_PAGE_SIZE - 1); // 计算页起始地址
    if (flash_erase_page(page_addr) != 0)
        return 2;
#endif

    FLASH_UNLOCK();

    uint32_t offset = 0;
    while (offset < size)
    {
        if (FLASH_WRITE_WORD(addr + offset, buf[offset / 4]) != 0)
        {
            FLASH_LOCK();
            return 3;
        }
        offset += 4;
    }

    FLASH_LOCK();
    return 0;
}

/**
 * @brief  从 Flash 读取数据
 * @param  addr: 起始地址
 * @param  buf: 数据缓冲区
 * @param  size: 数据大小（字节）
 */
void flash_read(uint32_t addr, uint32_t *buf, uint32_t size)
{
    if (addr < FLASH_BASE_ADDR || addr + size >= FLASH_END_ADDR)
        return;

    uint32_t *flash_ptr = (uint32_t *)addr;
    for (uint32_t i = 0; i < size / 4; i++)
    {
        buf[i] = flash_ptr[i];
    }
}
